Starting to call xfrd from xend.
40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h
40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c
40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h
+40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/xfrd/sxpr_parser.c
+40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/xfrd/sxpr_parser.h
40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c
40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h
40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c
$(MAKE) -C examples
$(MAKE) -C xentrace
$(MAKE) -C python
+ $(MAKE) -C xfrd
install: all
$(MAKE) -C libxutil install
$(MAKE) -C examples install
$(MAKE) -C xentrace install
$(MAKE) -C python install
+ $(MAKE) -C xfrd install
dist: $(TARGET)
$(MAKE) prefix=`pwd`/../../install dist=yes install
$(MAKE) -C examples clean
$(MAKE) -C xentrace clean
$(MAKE) -C python clean
+ $(MAKE) -C xfrd clean
#include "sys_net.h"
#include "sys_string.h"
+#ifdef __KERNEL__
+# include <linux/errno.h>
+#else
+# include <errno.h>
+#endif
+
/** @file
* All network data are kept in network order and only converted to
* host order for display. Network data includes IP addresses, port numbers and
*
* @param s input string
* @param address where to put the address
- * @return 0 on success, -1 on error
+ * @return 0 on success, negative on error
*/
int get_inet_addr(const char *s, unsigned long *address){
// Number of bits in a byte.
unsigned long addr = 0;
unsigned long v;
int i;
- int err = -1;
+ int err = -EINVAL;
// Bit shift for the current byte.
int shift = BYTE_BITS * (WORD_BYTES - 1);
char buf[64];
*
* @param name input hostname or address string
* @param address where to put the address
- * @return 1 if address found OK, 0 otherwise
+ * @return 0 if address found OK, nonzero otherwise
*/
int get_host_address(const char *name, unsigned long *address){
#ifdef __KERNEL__
- return get_inet_addr(name, address) == 0;
+ return get_inet_addr(name, address);
#else
struct hostent *host = gethostbyname(name);
if(!host){
- return 0;
+ return -EINVAL;
}
*address = ((struct in_addr *)(host->h_addr))->s_addr;
- return 1;
+ return 0;
#endif
}
*
* @param name service name
* @param port where to put the port
- * @return 1 if service port found OK, 0 otherwise
+ * @return 0 if service port found OK, negative otherwise
*/
int get_service_port(const char *name, unsigned long *port){
#ifdef __KERNEL__
- return 0;
+ return -ENOSYS;
#else
struct servent *service;
service = getservbyname(name, 0);
if(!service){
- return 0;
+ return -EINVAL;
}
*port = service->s_port;
- return 1;
+ return 0;
#endif
}
/** Convert a port number (in network order) to a service name.
*
* @param port the port number
- * @return service name if found OK, 0 otherwise
+ * @return service name if found OK, NULL otherwise
*/
char *get_port_service(unsigned long port){
#ifdef __KERNEL__
- return 0;
+ return NULL;
#else
struct servent *service = getservbyport(port, 0);
- return (service ? service->s_name : 0);
+ return (service ? service->s_name : NULL);
#endif
}
*
* @param s input to convert
* @param port where to put the port
- * @return 1 if port found OK, 0 otherwise
+ * @return 0 if port found OK, -1 otherwise
*/
int convert_service_to_port(const char *s, unsigned long *port){
- int ok = 0;
+ int err = 0;
unsigned long value;
- if(convert_atoul(s, &value)){
- ok = get_service_port(s, &value);
+ printf("%s> %s\n", __FUNCTION__, s);
+ if(convert_atoul(s, &value) == 0){
+ int ok = (0 <= value) && (value <= PORT_MAX);
+ printf("> value = %ld\n", value);
+ if(ok){
+ value = htons((unsigned short)value);
+ } else {
+ err = -EINVAL;
+ }
} else {
- ok = (0 <= value) && (value <= PORT_MAX);
- value = htons((unsigned short)value);
+ printf("> get_service_port...\n");
+ err = get_service_port(s, &value);
}
- *port = (ok ? value : 0);
- return ok;
+ *port = (err ? 0: value);
+ printf("%s< err=%d\n", __FUNCTION__, err);
+ return err;
}
#define MAC_ELEMENT_N 6 // Number of elements in a MAC address.
import XendDB
import XendDomainInfo
import XendConsole
+import XendMigrate
import EventServer
from xen.xend.server import SrvDaemon
"""
# Need a cancel too?
# Don't forget to cancel restart for it.
- pass
+ dom = int(id)
+ xmigrate = XendMigrate.instance()
+ return xmigrate.migrate_begin(dom, dst)
def domain_save(self, id, dst, progress=0):
"""Save domain state to file, destroy domain on success.
import XendDB
import EventServer; eserver = EventServer.instance()
-from xen.xend.packing import SxpPacker, SxpUnpacker
-from xen.xend import XendDomain
-xd = XendDomain.instance()
-
-
XFRD_PORT = 8002
XFR_PROTO_MAJOR = 1
class Migrate(Protocol):
def __init__(self, minfo):
- self.packer = None
- self.unpacker = None
+ self.parser = sxp.Parser()
self.minfo = minfo
def connectionMade(self):
- self.packer = SxpPacker(self.transport)
- self.unpacker = SxpPacker()
# Send hello.
- self.packer.pack(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR])
+ self.request(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR])
# Send migrate.
vmconfig = self.minfo.vmconfig()
if not vmconfig:
self.loseConnection()
return
- self.packer.pack(['xfr.migrate',
- self.minfo.src_dom,
- vmconfig,
- self.minfo.dst_host,
- self.minfo.dst_port])
+ self.request(['xfr.migrate',
+ self.minfo.src_dom,
+ vmconfig,
+ self.minfo.dst_host,
+ self.minfo.dst_port])
+
+ def request(self, req):
+ sxp.show(req, out=self.transport)
+ self.transport.write(' \n')
+
+ def loseConnection(self):
+ self.transport.loseConnection()
def connectionLost(self, reason):
self.minfo.closed(reason)
- def dataReceived(self, data):
- try:
- self.unpacker.reset(data)
- val = self.unpacker.unpack()
- print 'dataReceived>', 'val=', val
- op = val[0]
- op.replace('.', '_')
- if op.startwith('xfr_'):
- fn = getattr(self, op, self.unknown)
- else:
- fn = self.unknown
- fn(val)
- except Exception, ex:
- print 'dataReceived>', ex
- pass
+ def dispatch(self, val):
+ op = sxp.name(val)
+ op = op.replace('.', '_')
+ if op.startswith('xfr_'):
+ fn = getattr(self, op, self.unknown)
+ else:
+ fn = self.unknown()
+ fn(val)
+ def dataReceived(self, data):
+ self.parser.input(data)
+ if self.parser.ready():
+ val = self.parser.get_val()
+ self.dispatch(val)
+ if self.parser.at_eof():
+ self.loseConnection()
+
def unknown(self, val):
print 'unknown>', val
def xfr_progress(self, val):
print 'xfr_progress>', val
- def xfr_error(self, val):
+ def xfr_err(self, val):
# If we get an error with non-zero code the migrate failed.
# An error with code zero indicates hello success.
- err = int(val[1])
+ print 'xfr_err>', val
+ v = sxp.child(val)
+ print 'xfr_err>', type(v), v
+ err = int(sxp.child(val))
if not err: return
self.minfo.error(err);
self.loseConnection()
def xfr_ok(self, val):
# An ok indicates migrate completed successfully, and contains
# the new domain id on the remote system.
- dom = int(val[1])
+ print 'xfr_ok>', val
+ dom = int(sxp.child(val))
self.minfo.ok(dom)
self.loseConnection()
class MigrateClientFactory(ClientFactory):
def __init__(self, minfo):
- ClientFactory.__init__(self)
+ #ClientFactory.__init__(self)
self.minfo = minfo
def startedConnecting(self, connector):
self.state = 'begin'
self.src_host = socket.gethostname()
self.src_dom = dom
- self.dst_host = dst
+ self.dst_host = host
self.dst_port = port
self.dst_dom = None
self.start = 0
return sxpr
def vmconfig(self):
- dominfo = xd.domain_get(self.dom)
+ print 'vmconfig>'
+ from xen.xend import XendDomain
+ xd = XendDomain.instance()
+
+ dominfo = xd.domain_get(self.src_dom)
+ print 'vmconfig>', type(dominfo), dominfo
if dominfo:
- val = return sxp.to_string(dominfo)
+ val = sxp.to_string(dominfo.sxpr())
else:
val = None
- return None
+ print 'vmconfig<', 'val=', type(val), val
+ return val
def error(self, err):
self.state = 'error'
self.state = 'ok'
self.dst_dom = dom
- def close(self):
+ def closed(self, reason=None):
if self.state =='ok':
eserver.inject('xend.migrate.ok', self.sxpr())
else:
def migrate_get(self, id):
return self.migrate.get(id)
- def migrate_begin(self, dom, host):
+ def migrate_begin(self, dom, host, port=XFRD_PORT):
# Check dom for existence, not migrating already.
# Subscribe to migrate notifications (for updating).
id = self.nextid()
- info = XenMigrateInfo(id, dom, host, XFRD_PORT)
+ info = XendMigrateInfo(id, dom, host, port)
self._add_migrate(id, info)
mcf = MigrateClientFactory(info)
reactor.connectTCP('localhost', XFRD_PORT, mcf)
- return info.deferred
+ return info
def instance():
global inst
UTIL_LIB_SRC += marshal.c
UTIL_LIB_SRC += string_stream.c
UTIL_LIB_SRC += sxpr.c
-#UTIL_LIB_SRC += sxpr_parser.c
+UTIL_LIB_SRC += sxpr_parser.c
UTIL_LIB_SRC += sys_net.c
UTIL_LIB_SRC += sys_string.c
#UTIL_LIB_SRC += util.c
#include "connection.h"
#include "file_stream.h"
#include "lzi_stream.h"
+#include "sxpr_parser.h"
#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
#define wprintf(fmt, args...) fprintf(stderr, "[WARN] %s" fmt, __FUNCTION__, ##args)
if(conn->out) IOStream_close(conn->out);
shutdown(conn->sock, 2);
}
+
+int Conn_sxpr(Conn *conn, Sxpr *sxpr){
+ int err = 0;
+ Sxpr val = ONONE;
+ int c = 0;
+
+ dprintf(">\n");
+ if(!conn->parser){
+ conn->parser = Parser_new();
+ set_error_stream(conn->parser, iostdout);
+ }
+ while(!err && c >= 0 && !Parser_ready(conn->parser)){
+ c = IOStream_getc(conn->in);
+ printf("%c", (char)c);
+ if(c < 0){
+ err = Parser_input_eof(conn->parser);
+ } else {
+ err = Parser_input_char(conn->parser, c);
+ }
+ }
+ if(Parser_ready(conn->parser)){
+ val = Parser_get_val(conn->parser);
+ }
+ if(err){
+ objfree(val);
+ val = ONONE;
+ }
+ *sxpr = val;
+ dprintf("< err=%d\n", err);
+ return err;
+}
#include <netinet/in.h>
#include "iostream.h"
+#include "sxpr_parser.h"
/** A connection.
* The underlying transport is a socket.
int sock;
IOStream *in;
IOStream *out;
+ Parser *parser;
} Conn;
enum {
extern int Conn_connect(Conn *conn, int flags, struct in_addr ipaddr, uint16_t port);
extern void Conn_close(Conn *conn);
+extern int Conn_sxpr(Conn *conn, Sxpr *sxpr);
+
#endif /* ! _VFC_CONNECTION_H_ */
--- /dev/null
+
+#ifdef __KERNEL__
+# include <linux/config.h>
+# include <linux/module.h>
+# include <linux/kernel.h>
+# include <linux/string.h>
+# include <linux/errno.h>
+#else
+# include <stdlib.h>
+# include <errno.h>
+#endif
+
+#include "iostream.h"
+#include "lexis.h"
+#include "sxpr_parser.h"
+#include "sys_string.h"
+#include "enum.h"
+
+/** @file
+ * Sxpr parsing.
+ *
+ * So that the parser does not leak memory, all sxprs constructed by
+ * the parser must be freed on error. On successful parse the sxpr
+ * returned becomes the responsibility of the caller.
+ *
+ * @author Mike Wray <mike.wray@hpl.hp.com>
+ */
+
+#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
+#define printf(fmt, args...) IOStream_print(iostdout, fmt, ##args)
+
+static void reset(Parser *z);
+static int inputchar(Parser *p, char c);
+static int savechar(Parser *p, char c);
+extern void parse_error(Parser *in);
+extern void parse_error_id(Parser *in, ParseErrorId id);
+
+static int begin_start(Parser *p, char c);
+static int state_start(Parser *p, char c);
+static int end_start(Parser *p);
+
+static int begin_comment(Parser *p, char c);
+static int state_comment(Parser *p, char c);
+static int end_comment(Parser *p);
+
+static int begin_string(Parser *p, char c);
+static int state_string(Parser *p, char c);
+static int end_string(Parser *p);
+static int state_escape(Parser *p, char c);
+static int state_octal(Parser *p, char c);
+static int state_hex(Parser *p, char c);
+
+static int begin_atom(Parser *p, char c);
+static int state_atom(Parser *p, char c);
+static int end_atom(Parser *p);
+
+static int state_list(Parser *p, char c);
+static int begin_list(Parser *p, char c);
+static int end_list(Parser *p);
+
+/** Print a parse error.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void eprintf(Parser *in, char *msg, ...){
+ va_list args;
+ if(in->error_out){
+ va_start(args, msg);
+ IOStream_vprint(in->error_out, msg, args);
+ va_end(args);
+ }
+}
+
+/** Print a parse warning.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void wprintf(Parser *in, char *msg, ...){
+ va_list args;
+ if(in->error_out){
+ va_start(args, msg);
+ IOStream_vprint(in->error_out, msg, args);
+ va_end(args);
+ }
+}
+
+/*============================================================================*/
+
+/** Record defining the message for a parse error. */
+typedef struct {
+ ParseErrorId id;
+ char *message;
+} ParseError;
+
+/** Format for printing parse error messages. */
+#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
+
+/** Message catalog for the parse error codes. */
+static ParseError catalog[] = {
+ { PARSE_ERR_UNSPECIFIED, "unspecified error" },
+ { PARSE_ERR_NOMEM, "out of memory" },
+ { PARSE_ERR_UNEXPECTED_EOF, "unexpected end of input" },
+ { PARSE_ERR_TOKEN_TOO_LONG, "token too long" },
+ { PARSE_ERR_INVALID_SYNTAX, "syntax error" },
+ { PARSE_ERR_INVALID_ESCAPE, "invalid escape" },
+ { 0, NULL }
+};
+
+/** Number of entries in the message catalog. */
+const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
+
+void ParserState_free(ParserState *z){
+ if(!z) return;
+ objfree(z->val);
+ deallocate(z);
+}
+
+int ParserState_new(ParserStateFn *fn, char *name,
+ ParserState *parent, ParserState **val){
+ int err = 0;
+ ParserState *z;
+ z = ALLOCATE(ParserState);
+ if(z){
+ z->name = name;
+ z->fn = fn;
+ z->parent = parent;
+ z->val = ONULL;
+ } else {
+ err = -ENOMEM;
+ }
+ if(!err) *val = z;
+ return err;
+}
+
+/** Free a parser.
+ * No-op if the parser is null.
+ *
+ * @param z parser
+ */
+void Parser_free(Parser *z){
+ if(!z) return;
+ objfree(z->val);
+ z->val = ONONE;
+ deallocate(z);
+}
+
+/** Create a new parser. The error stream defaults to null.
+ */
+Parser * Parser_new(void){
+ Parser *z = ALLOCATE(Parser);
+ int err = -ENOMEM;
+
+ if(!z) goto exit;
+ err = 0;
+ reset(z);
+ exit:
+ if(err){
+ Parser_free(z);
+ z = NULL;
+ }
+ return z;
+}
+
+/** Get the next character.
+ * Records the character read in the parser,
+ * and sets the line and character counts.
+ *
+ * @param p parser
+ * @return error flag: 0 on success, non-zero on error
+ */
+static int inputchar(Parser *p, char c){
+ int err = 0;
+ if(c=='\n'){
+ p->line_no++;
+ p->char_no = 0;
+ } else {
+ p->char_no++;
+ }
+ return err;
+}
+
+static int savechar(Parser *p, char c){
+ int err = 0;
+ if(p->buf_i >= p->buf_n){
+ err = -ENOMEM;
+ goto exit;
+ }
+ p->buf[p->buf_i] = c;
+ p->buf_i++;
+ exit:
+ return err;
+}
+
+int Parser_input_char(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ //skip;
+ } else {
+ inputchar(p, c);
+ }
+ if(!p->state){
+ err = begin_start(p, c);
+ if(err) goto exit;
+ }
+ err = p->state->fn(p, c);
+ exit:
+ return err;
+}
+
+int Parser_input_eof(Parser *p){
+ int err = 0;
+ p->eof = 1;
+ err = Parser_input_char(p, IOSTREAM_EOF);
+ return err;
+}
+
+int Parser_input(Parser *p, char *buf, int buf_n){
+ int err = 0;
+ int i = 0;
+ if(buf_n <= 0){
+ err = Parser_input_eof(p);
+ goto exit;
+ }
+ for(i = 0; i<buf_n; i++){
+ err = Parser_input_char(p, buf[i]);
+ if(err) goto exit;
+ }
+ exit:
+ err = (err < 0 ? err : buf_n);
+ return err;
+}
+
+int Parser_push(Parser *p, ParserStateFn *fn, char *name){
+ int err = 0;
+ err = ParserState_new(fn, name, p->state, &p->state);
+ return err;
+}
+
+int Parser_pop(Parser *p){
+ int err = 0;
+ ParserState *s = p->state;
+ p->state = s->parent;
+ ParserState_free(s);
+ return err;
+}
+
+int Parser_return(Parser *p){
+ int err = 0;
+ Sxpr val = ONONE;
+ if(!p->state){
+ err = -EINVAL;
+ goto exit;
+ }
+ val = p->state->val;
+ p->state->val = ONONE;
+ err = Parser_pop(p);
+ if(err) goto exit;
+ if(p->state){
+ err = cons_push(&p->state->val, val);
+ } else {
+ val = nrev(val);
+ p->val = val;
+ }
+ exit:
+ if(err){
+ objfree(val);
+ }
+ return err;
+}
+
+/** Determine if a character is a separator.
+ *
+ * @param p parser
+ * @param c character to test
+ * @return 1 if a separator, 0 otherwise
+ */
+static int is_separator(Parser *p, char c){
+ return in_sep_class(c);
+}
+
+/** Return the current token.
+ * The return value points at the internal buffer, so
+ * it must not be modified (or freed). Use copy_token() if you need a copy.
+ *
+ * @param p parser
+ * @return token
+ */
+char *peek_token(Parser *p){
+ return p->buf;
+}
+
+/** Return a copy of the current token.
+ * The returned value should be freed when finished with.
+ *
+ * @param p parser
+ * @return copy of token
+ */
+char *copy_token(Parser *p){
+ return strdup(peek_token(p));
+}
+
+static int do_intern(Parser *p){
+ int err = 0;
+ Sxpr obj = intern(peek_token(p));
+ if(NOMEMP(obj)){
+ err = -ENOMEM;
+ } else {
+ p->state->val = obj;
+ }
+ return err;
+}
+
+static int do_string(Parser *p){
+ int err = 0;
+ Sxpr obj;
+ obj = string_new(peek_token(p));
+ if(NOMEMP(obj)){
+ err = -ENOMEM;
+ } else {
+ p->state->val = obj;
+ }
+ return err;
+}
+
+void newtoken(Parser *p){
+ memset(p->buf, 0, p->buf_n);
+ p->buf_i = 0;
+ p->tok_begin_line = p->line_no;
+ p->tok_begin_char = p->char_no;
+}
+
+int get_escape(char c, char *d){
+ int err = 0;
+ switch(c){
+ case 'a': *d = '\a'; break;
+ case 'b': *d = '\b'; break;
+ case 'f': *d = '\f'; break;
+ case 'n': *d = '\n'; break;
+ case 'r': *d = '\r'; break;
+ case 't': *d = '\t'; break;
+ case 'v': *d = '\v'; break;
+ case c_escape: *d = c_escape; break;
+ case c_single_quote: *d = c_single_quote; break;
+ case c_double_quote: *d = c_double_quote; break;
+ default:
+ err = -EINVAL;
+ }
+ return err;
+}
+
+int Parser_ready(Parser *p){
+ return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
+}
+
+Sxpr Parser_get_val(Parser *p){
+ Sxpr v = ONONE;
+ if(CONSP(p->val)){
+ v = CAR(p->val);
+ p->val = CDR(p->val);
+ } else if (CONSP(p->start_state->val)){
+ p->val = p->start_state->val;
+ p->val = nrev(p->val);
+ p->start_state->val = ONULL;
+ v = CAR(p->val);
+ p->val = CDR(p->val);
+ }
+ return v;
+}
+
+Sxpr Parser_get_all(Parser *p){
+ Sxpr v = ONULL;
+ if(CONSP(p->val)){
+ v = p->val;
+ p->val = ONONE;
+ } else if(CONSP(p->start_state->val)){
+ v = p->start_state->val;
+ p->start_state->val = ONULL;
+ v = nrev(v);
+ }
+ return v;
+}
+
+int begin_start(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_start, "start");
+ if(err) goto exit;
+ p->start_state = p->state;
+ exit:
+ return err;
+}
+
+int state_start(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ err = end_start(p);
+ } else if(in_space_class(c)){
+ //skip
+ } else if(in_comment_class(c)){
+ begin_comment(p, c);
+ } else if(c == c_list_open){
+ begin_list(p, c);
+ } else if(c == c_list_close){
+ parse_error(p);
+ err = -EINVAL;
+ } else if(in_string_quote_class(c)){
+ begin_string(p, c);
+ } else if(in_printable_class(c)){
+ begin_atom(p, c);
+ } else if(c == 0x04){
+ //ctrl-D, EOT: end-of-text.
+ Parser_input_eof(p);
+ } else {
+ parse_error(p);
+ err = -EINVAL;
+ }
+ return err;
+}
+
+int end_start(Parser *p){
+ int err = 0;
+ err = Parser_return(p);
+ return err;
+}
+
+int begin_comment(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_comment, "comment");
+ if(err) goto exit;
+ err = inputchar(p, c);
+ exit:
+ return err;
+}
+
+int state_comment(Parser *p, char c){
+ int err = 0;
+ if(c == '\n' || at_eof(p)){
+ err = end_comment(p);
+ } else {
+ err = inputchar(p, c);
+ }
+ return err;
+}
+
+int end_comment(Parser *p){
+ return Parser_pop(p);
+}
+
+int begin_string(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_string, "string");
+ if(err) goto exit;
+ newtoken(p);
+ p->state->delim = c;
+ exit:
+ return err;
+}
+
+int state_string(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ } else if(c == p->state->delim){
+ err = end_string(p);
+ } else if(c == '\\'){
+ err = Parser_push(p, state_escape, "escape");
+ } else {
+ err = savechar(p, c);
+ }
+ return err;
+}
+
+int end_string(Parser *p){
+ int err = 0;
+ err = do_string(p);
+ if(err) goto exit;
+ err = Parser_return(p);
+ exit:
+ return err;
+}
+
+int state_escape(Parser *p, char c){
+ int err = 0;
+ char d;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ goto exit;
+ }
+ if(get_escape(c, &d) == 0){
+ err = savechar(p, d);
+ if(err) goto exit;
+ err = Parser_pop(p);
+ } else if(c == 'x'){
+ p->state->fn = state_hex;
+ p->state->ival = 0;
+ p->state->count = 0;
+ } else {
+ p->state->fn = state_octal;
+ p->state->ival = 0;
+ p->state->count = 0;
+ err = Parser_input_char(p, c);
+ }
+ exit:
+ return err;
+}
+
+int octaldone(Parser *p){
+ int err = 0;
+ char d = (char)(p->state->ival & 0xff);
+ err = Parser_pop(p);
+ if(err) goto exit;
+ err = Parser_input_char(p, d);
+ exit:
+ return err;
+}
+
+int octaldigit(Parser *p, char c){
+ int err = 0;
+ p->state->ival *= 8;
+ p->state->ival += c - '0';
+ p->state->count++;
+ if(err) goto exit;
+ if(p->state->ival < 0 || p->state->ival > 0xff){
+ parse_error(p);
+ err = -EINVAL;
+ goto exit;
+ }
+ if(p->state->count == 3){
+ err = octaldone(p);
+ }
+ exit:
+ return err;
+}
+
+int state_octal(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ goto exit;
+ } else if('0' <= c && c <= '7'){
+ err = octaldigit(p, c);
+ } else {
+ err = octaldone(p);
+ if(err) goto exit;
+ Parser_input_char(p, c);
+ }
+ exit:
+ return err;
+}
+
+int hexdone(Parser *p){
+ int err = 0;
+ char d = (char)(p->state->ival & 0xff);
+ err = Parser_pop(p);
+ if(err) goto exit;
+ err = Parser_input_char(p, d);
+ exit:
+ return err;
+}
+
+int hexdigit(Parser *p, char c, char d){
+ int err = 0;
+ p->state->ival *= 16;
+ p->state->ival += c - d;
+ p->state->count++;
+ if(err) goto exit;
+ if(p->state->ival < 0 || p->state->ival > 0xff){
+ parse_error(p);
+ err = -EINVAL;
+ goto exit;
+ }
+ if(p->state->count == 2){
+ err = hexdone(p);
+ }
+ exit:
+ return err;
+}
+
+int state_hex(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ goto exit;
+ } else if('0' <= c && c <= '9'){
+ err = hexdigit(p, c, '0');
+ } else if('A' <= c && c <= 'F'){
+ err = hexdigit(p, c, 'A');
+ } else if('a' <= c && c <= 'f'){
+ err = hexdigit(p, c, 'a');
+ } else if(p->state->count){
+ err =hexdone(p);
+ if(err) goto exit;
+ Parser_input_char(p, c);
+ }
+ exit:
+ return err;
+}
+
+int begin_atom(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_atom, "atom");
+ if(err) goto exit;
+ newtoken(p);
+ err = savechar(p, c);
+ exit:
+ return err;
+}
+
+int state_atom(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ err = end_atom(p);
+ } else if(is_separator(p, c) ||
+ in_space_class(c) ||
+ in_comment_class(c)){
+ err = end_atom(p);
+ if(err) goto exit;
+ err = Parser_input_char(p, c);
+ } else {
+ err = savechar(p, c);
+ }
+ exit:
+ return err;
+}
+
+int end_atom(Parser *p){
+ int err = 0;
+ err = do_intern(p);
+ if(err) goto exit;
+ err = Parser_return(p);
+ exit:
+ return err;
+}
+
+int state_list(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ } else if(c == c_list_close){
+ p->state->val = nrev(p->state->val);
+ err = end_list(p);
+ } else {
+ err = state_start(p, c);
+ }
+ return err;
+
+}
+
+int begin_list(Parser *p, char c){
+ return Parser_push(p, state_list, "list");
+}
+
+int end_list(Parser *p){
+ return Parser_return(p);
+}
+
+/** Reset the fields of a parser to initial values.
+ *
+ * @param z parser
+ */
+static void reset(Parser *z){
+ IOStream *error_out = z->error_out;
+ int flags = z->flags;
+ memzero(z, sizeof(Parser));
+ z->buf_n = sizeof(z->buf) - 1;
+ z->buf_i = 0;
+ z->line_no = 1;
+ z->char_no = 0;
+ z->error_out = error_out;
+ z->flags = flags;
+}
+
+/** Set the parser error stream.
+ * Parse errors are reported on the the error stream if it is non-null.
+ *
+ * @param z parser
+ * @param error_out error stream
+ */
+void set_error_stream(Parser *z, IOStream *error_out){
+ if(z){
+ z->error_out = error_out;
+ }
+}
+
+/** Get the parser error message for an error code.
+ *
+ * @param id error code
+ * @return error message (empty string if the code is unknown)
+ */
+static char *get_message(ParseErrorId id){
+ int i;
+ for(i=0; i<catalog_n; i++){
+ if(id == catalog[i].id){
+ return catalog[i].message;
+ }
+ }
+ return "";
+}
+
+/** Get the line number.
+ *
+ * @param in parser
+ */
+int get_line(Parser *in){
+ return in->line_no;
+}
+
+/** Get the column number.
+ *
+ * @param in parser
+ */
+int get_column(Parser *in){
+ return in->char_no;
+}
+
+/** Get the line number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_line(Parser *in){
+ return in->tok_begin_line;
+}
+
+/** Get the column number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_column(Parser *in){
+ return in->tok_begin_char;
+}
+
+/** Report a parse error.
+ * Does nothing if the error stream is null or there is no error.
+ *
+ * @param in parser
+ */
+static void report_error(Parser *in){
+ if(in->error_out && in->err){
+ char *msg = get_message(in->err);
+ char *tok = peek_token(in);
+ IOStream_print(in->error_out, PARSE_ERR_FMT,
+ get_tok_line(in), get_tok_column(in), msg);
+ if(tok && tok[0]){
+ IOStream_print(in->error_out, " '%s'", tok);
+ }
+ IOStream_print(in->error_out, "\n");
+ }
+}
+
+/** Get the error message for the current parse error code.
+ * Does nothing if there is no error.
+ *
+ * @param in parser
+ * @param buf where to place the message
+ * @param n maximum number of characters to place in buf
+ * @return current error code (zero for no error)
+ */
+int parse_error_message(Parser *in, char *buf, int n){
+ if(in->err){
+ char *msg = get_message(in->err);
+ snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
+ }
+ return in->err;
+}
+
+/** Flag an unspecified parse error. All subsequent reads will fail.
+ *
+ * @param in parser
+ */
+void parse_error(Parser *in){
+ parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
+}
+
+/** Flag a parse error. All subsequent reads will fail.
+ * Does not change the parser error code if it is already set.
+ *
+ * @param in parser
+ * @param id error code
+ */
+void parse_error_id(Parser *in, ParseErrorId id){
+ if(!in->err){
+ in->err = id;
+ report_error(in);
+ }
+}
+
+/** Test if the parser's error flag is set.
+ *
+ * @param in parser
+ * @return 1 if set, 0 otherwise
+ */
+int has_error(Parser *in){
+ return (in->err > 0);
+}
+
+/** Test if the parser is at end of input.
+ *
+ * @param in parser
+ * @return 1 if at EOF, 0 otherwise
+ */
+int at_eof(Parser *p){
+ return p->eof;
+}
+
+//#define SXPR_PARSER_MAIN
+#ifdef SXPR_PARSER_MAIN
+/* Stuff for standalone testing. */
+
+#include "file_stream.h"
+#include "string_stream.h"
+
+int stringof(Sxpr exp, char **s){
+ int err = 0;
+ if(ATOMP(exp)){
+ *s = atom_name(exp);
+ } else if(STRINGP(exp)){
+ *s = string_string(exp);
+ } else {
+ err = -EINVAL;
+ *s = NULL;
+ }
+ return err;
+}
+
+int child_string(Sxpr exp, Sxpr key, char **s){
+ int err = 0;
+ Sxpr val = sxpr_child_value(exp, key, ONONE);
+ err = stringof(val, s);
+ return err;
+}
+
+int intof(Sxpr exp, int *v){
+ int err = 0;
+ char *s;
+ unsigned long l;
+ if(INTP(exp)){
+ *v = OBJ_INT(exp);
+ } else {
+ err = stringof(exp, &s);
+ if(err) goto exit;
+ err = convert_atoul(s, &l);
+ *v = (int)l;
+ }
+ exit:
+ return err;
+}
+
+int child_int(Sxpr exp, Sxpr key, int *v){
+ int err = 0;
+ Sxpr val = sxpr_child_value(exp, key, ONONE);
+ err = intof(val, v);
+ return err;
+}
+
+int eval_vnet(Sxpr exp){
+ int err = 0;
+ Sxpr oid = intern("id");
+ int id;
+ err = child_int(exp, oid, &id);
+ if(err) goto exit;
+ dprintf("> vnet id=%d\n", id);
+ exit:
+ dprintf("< err=%d\n", err);
+ return err;
+}
+
+int eval_connect(Sxpr exp){
+ int err = 0;
+ Sxpr ovif = intern("vif");
+ Sxpr ovnet = intern("vnet");
+ char *vif;
+ int vnet;
+
+ err = child_string(exp, ovif, &vif);
+ if(err) goto exit;
+ err = child_int(exp, ovnet, &vnet);
+ if(err) goto exit;
+ dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
+ exit:
+ dprintf("< err=%d\n", err);
+ return err;
+}
+
+int eval(Sxpr exp){
+ int err = 0;
+ Sxpr oconnect = intern("connect");
+ Sxpr ovnet = intern("vnet");
+
+ if(sxpr_elementp(exp, ovnet)){
+ err = eval_vnet(exp);
+ } else if(sxpr_elementp(exp, oconnect)){
+ err = eval_connect(exp);
+ } else {
+ err = -EINVAL;
+ }
+ return err;
+}
+
+/** Main program for testing.
+ * Parses input and prints it.
+ *
+ * @param argc number of arguments
+ * @param argv arguments
+ * @return error code
+ */
+int main(int argc, char *argv[]){
+ Parser *pin;
+ int err = 0;
+ char buf[1024];
+ int k;
+ Sxpr obj;
+ //Sxpr l, x;
+ int i = 0;
+
+ pin = Parser_new();
+ set_error_stream(pin, iostdout);
+ dprintf("> parse...\n");
+ while(1){
+ k = fread(buf, 1, 1, stdin);
+ err = Parser_input(pin, buf, k);
+ while(Parser_ready(pin)){
+ obj = Parser_get_val(pin);
+ printf("obj %d\n", i++);
+ objprint(iostdout, obj, 0); printf("\n");
+ }
+ if(k <= 0) break;
+ }
+/* obj = Parser_get_all(pin); */
+/* for(l = obj ; CONSP(l); l = CDR(l)){ */
+/* x = CAR(l); */
+/* objprint(iostdout, x, 0); printf("\n"); */
+/* eval(x); */
+/* } */
+ dprintf("> err=%d\n", err);
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version. This library is
+ * distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _XUTIL_SXPR_PARSER_H_
+#define _XUTIL_SXPR_PARSER_H_
+
+#include "sxpr.h"
+#include "iostream.h"
+
+/** @file
+ * Sxpr parsing definitions.
+ */
+
+/** Size of a parser input buffer.
+ * Tokens read must fit into this size (including trailing null).
+ */
+#define PARSER_BUF_SIZE 1024
+
+struct Parser;
+typedef int ParserStateFn(struct Parser *, char c);
+
+typedef struct ParserState {
+ struct ParserState *parent;
+ Sxpr val;
+ int ival;
+ int count;
+ char delim;
+ ParserStateFn *fn;
+ char *name;
+} ParserState;
+
+/** Structure representing an input source for the parser.
+ * Can read from any IOStream implementation.
+ */
+typedef struct Parser {
+ Sxpr val;
+ /** Error reporting stream (null for no reports). */
+ IOStream *error_out;
+ int eof;
+ /** Error flag. Non-zero if there has been a read error. */
+ int err;
+ /** Line number on input (from 1). */
+ int line_no;
+ /** Column number of input (reset on new line). */
+ int char_no;
+ /** Lookahead character. */
+ char c;
+ /** Buffer for reading tokens. */
+ char buf[PARSER_BUF_SIZE];
+ /** Size of token buffer. */
+ int buf_n;
+ int buf_i;
+ /** Line the last token started on. */
+ int tok_begin_line;
+ /** Character number the last token started on. */
+ int tok_begin_char;
+ /** Parsing flags. */
+ int flags;
+ ParserState *state;
+ ParserState *start_state;
+} Parser;
+
+/** Parser error codes. */
+typedef enum {
+ PARSE_ERR_NONE=0,
+ PARSE_ERR_UNSPECIFIED,
+ PARSE_ERR_NOMEM,
+ PARSE_ERR_UNEXPECTED_EOF,
+ PARSE_ERR_TOKEN_TOO_LONG,
+ PARSE_ERR_INVALID_SYNTAX,
+ PARSE_ERR_INVALID_ESCAPE,
+} ParseErrorId;
+
+
+/** Parser flags. */
+//enum {
+//};
+
+/** Raise some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_raise(Parser *in, int flags){
+ in->flags |= flags;
+}
+
+/** Lower some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_lower(Parser *in, int flags){
+ in->flags &= ~flags;
+}
+
+/** Clear all parser flags.
+ *
+ * @param in parser
+ */
+inline static void parser_flags_clear(Parser *in){
+ in->flags = 0;
+}
+
+extern void Parser_free(Parser *z);
+extern Parser * Parser_new(void);
+extern int Parser_input(Parser *p, char *buf, int buf_n);
+extern int Parser_input_eof(Parser *p);
+extern int Parser_input_char(Parser *p, char c);
+extern void set_error_stream(Parser *z, IOStream *error_out);
+
+extern int parse_error_message(Parser *in, char *buf, int n);
+extern int has_error(Parser *in);
+extern int at_eof(Parser *in);
+
+int Parser_ready(Parser *p);
+Sxpr Parser_get_val(Parser *p);
+Sxpr Parser_get_all(Parser *p);
+
+#endif /* ! _XUTIL_SXPR_PARSER_H_ */
if(d > buf_n) d = buf_n;
err = marshal_bytes(io, buf, d);
if(err) goto exit;
- //dprintf("> k=%d n=%d\n", k, n);
+ dprintf("> k=%d n=%d\n", k, n);
}
exit:
if(d > buf_n) d = buf_n;
err = unmarshal_bytes(io, buf, d);
if(err) goto exit;
- //dprintf("> k=%d n=%d\n", k, n);
+ dprintf("> k=%d n=%d\n", k, n);
}
exit:
#else
#include "sys_net.h"
#include "sys_string.h"
-#include "xdr.h"
+//#include "xdr.h"
#include "enum.h"
#include "xfrd.h"
err = stringof(exp, &h);
if(err) goto exit;
if(get_host_address(h, &a)){
- *v = a;
- } else {
err = -EINVAL;
+ goto exit;
}
+ *v = a;
exit:
dprintf("< err=%d v=%x\n", err, *v);
return err;
unsigned long p;
err = stringof(exp, &s);
if(err) goto exit;
- if(get_service_port(s, &p)){
- *v = p;
- } else {
+ err = convert_service_to_port(s, &p);
+ if(err){
err = -EINVAL;
+ goto exit;
}
+ *v = p;
}
exit:
dprintf("< err=%d v=%u\n", err, *v);
*/
int xfr_error(Conn *conn, int errcode){
int err = 0;
+
if(!conn->out) return -ENOTCONN;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_err);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(errcode));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- exit:
- return err;
+ if(errcode <0) errcode = -errcode;
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_err), errcode);
+ return (err < 0 ? err : 0);
}
/** Read a response message - error or ok.
dprintf(">\n");
if(!conn->out) return -ENOTCONN;
- err = unpack_sxpr(conn->in, &sxpr);
+ err = Conn_sxpr(conn, &sxpr);
if(err) goto exit;
if(sxpr_elementp(sxpr, oxfr_err)){
int errcode;
Sxpr sxpr;
if(!conn->in) return -ENOTCONN;
dprintf(">\n");
- err = unpack_sxpr(conn->in, &sxpr);
+ err = Conn_sxpr(conn, &sxpr);
if(err) goto exit;
if(!sxpr_elementp(sxpr, oxfr_hello)){
dprintf("> sxpr_elementp test failed\n");
int xfr_send_hello(Conn *conn){
int err = 0;
dprintf(">\n");
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_hello);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(XFR_PROTO_MAJOR));
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(XFR_PROTO_MINOR));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
+
+ err = IOStream_print(conn->out, "(%s %d %d)",
+ atom_name(oxfr_hello),
+ XFR_PROTO_MAJOR,
+ XFR_PROTO_MINOR);
+ if(err < 0) goto exit;
IOStream_flush(conn->out);
dprintf("> xfr_response...\n");
err = xfr_response(conn);
int xfr_send_xfr(Conn *conn, uint32_t vmid){
int err;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_xfr);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(vmid));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- if(err) goto exit;
- exit:
- return err;
+
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_xfr), vmid);
+ return (err < 0 ? err : 0);
}
int xfr_send_ok(Conn *conn, uint32_t vmid){
int err = 0;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_ok);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(vmid));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- exit:
- return err;
+
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_ok), vmid);
+ return (err < 0 ? err : 0);
}
int xfr_send_suspend(Conn *conn, uint32_t vmid){
int err = 0;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_suspend);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(vmid));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- exit:
- return err;
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_suspend), vmid);
+ return (err < 0 ? err : 0);
}
/** Get vm state. Send transfer message.
// Send xfr message and the domain state.
err = xfr_send_xfr(peer, state->vmid);
if(err) goto exit;
- err = xen_domain_snd(xend, peer->out, state->vmid, state->vmconfig, state->vmconfig_n);
+ err = xen_domain_snd(xend, peer->out,
+ state->vmid, state->vmconfig, state->vmconfig_n);
if(err) goto exit;
IOStream_flush(peer->out);
// Read the response from the peer.
- err = unpack_sxpr(peer->in, &sxpr);
+ err = Conn_sxpr(peer, &sxpr);
if(err) goto exit;
if(sxpr_elementp(sxpr, oxfr_err)){
// Error.
dprintf(">\n");
err = Conn_init(conn, flags, peersock, peer_in);
if(err) goto exit;
+ dprintf(">xfr_hello... \n");
err = xfr_hello(conn);
if(err) goto exit;
- err = unpack_sxpr(conn->in, &sxpr);
+ dprintf("> sxpr...\n");
+ err = Conn_sxpr(conn, &sxpr);
if(err) goto exit;
+ dprintf("> sxpr=\n");
+ objprint(iostdout, sxpr, PRINT_TYPE); IOStream_print(iostdout, "\n");
if(sxpr_elementp(sxpr, oxfr_migrate)){
// Migrate message from xend.
uint32_t addr;
self.sockin = self.sock.makefile("r")
self.sockout = self.sock.makefile("w")
- self.packer = SxpPacker(self.sockout)
- self.unpacker = SxpUnpacker(self.sockin)
#pass
def request(self, req):
print "request>", req
- self.packer.pack(req)
+ sxp.show(req, out=self.sockout)
self.sockout.flush()
print "request<"
def read(self):
while(1):
- v = self.unpacker.unpack()
+ v = self.sockin.read()
print 'read>', v
- if v[0] == 'xfr.err' and v[1]: return
- if v[0] == 'xfr.ok': return
+ #if v[0] == 'xfr.err' and v[1]: return
+ #if v[0] == 'xfr.ok': return
XFR_PROTO_MAJOR = 1
XFR_PROTO_MINOR = 0